// common/http.interceptor.js
import $store from '@/store/index.js';
import cryptojs from '@/common/cryptojs.js'
const codeMessage = {
	404: '您所请求的资源无法找到',
	500: '服务器内部错误，无法完成请求',
};

let tokenRefreshQueue = []; // 用于存放待处理的请求
let isRefreshingToken = false; // 标志是否正在刷新token
const install = (Vue, vm) => {
	// 这个配置是一次配置，全局通用的，具体参数见 https://www.uviewui.com/js/http.html
	uni.$u.http.setConfig((config) => {
		// 域名设置
		config.baseURL = uni.$config.baseUrl;
		// 全局header
		config.header = {};
		config.timeout = 10000;
		// 
		config.method = '';
		// 设置为json，返回后会对数据进行一次JSON.parse()
		config.dataType = 'json';
		// 
		config.responseType = 'text';
		// 注：如果局部custom与全局custom有同名属性，则后面的属性会覆盖前面的属性，相当于Object.assign(全局，局部)
		config.custom = {
			//请求接口是否返回错误
			requestError:true,
			// 请求接口展示Loading
			ShowLoading: false,
			// Loading中是否遮罩
			LoadingMask: true,
			// Loading文本
			LoadingText: '正在加载',
		}; // 全局自定义参数默认值
		// 验证 ssl 证书 仅5+App安卓端支持（HBuilderX 2.3.3+）
		config.sslVerify = false;
		// DNS解析时优先使用ipv4 仅 App-Android 支持 (HBuilderX 2.8.0+)
		config.firstIpv4 = false;
		// 局部优先级高于全局，返回当前请求的task,options。请勿在此处修改options。非必填
		// getTask: (task, options) => {
		// 相当于设置了请求超时时间500ms
		//   setTimeout(() => {
		//     task.abort()
		//   }, 500)
		// },
		// 全局自定义验证器。参数为statusCode 且必存在，不用判断空情况。
		// config.validateStatus = (statusCode) => { // statusCode 必存在。此处示例为全局默认配置
		// 	return statusCode >= 200 && statusCode < 300
		// };
		return config;
	});

	// 请求拦截部分，如配置，每次请求前都会执行
	uni.$u.http.interceptors.request.use((config) => {
		// 如果需要重试，并且是第一次请求的时候添加加载，重试期间不需要重新加载
		if (config.custom.retry) {
			if (config.custom.ShowLoading && config.custom.retry_number == config.custom.retry_number_all) {
				uni.showLoading({
					title: config.custom.LoadingText || '正在加载',
					mask: config.custom.LoadingMask || true
				});
			}
		}else{
			if (config.custom.ShowLoading) {
				uni.showLoading({
					title: config.custom.LoadingText || '正在加载',
					mask: config.custom.LoadingMask || true
				});
			}
		}
		if(!config.custom.noToken){
			const token = uni.getStorageSync('token');
			if (!token) {
			   //如果需要重试不再重试
			  if(config.custom.retry){
				  config.custom.retry = false;
			  }
			  return Promise.reject({config})
			}
			config.header.authorization = 'Bearer '+token;
		}
		config.header.lang = uni.getLocale()
		return config;
	}, config => { // 可使用async await 做异步操作
		//如果需要重试不再重试
		if(config.custom.retry){
		    config.custom.retry = false;
		}
		return Promise.reject({config})
	})

	// 响应拦截，如配置，每次请求结束都会执行本方法
	uni.$u.http.interceptors.response.use(async (res) => {
		console.warn(res);
		if (res.config.custom.ShowLoading) {
			uni.hideLoading();
		}
		// if 状态码是否正常
		if (res.statusCode == 200) {
			// 返回原始数据
			if(res.config.custom.native){
				return res
			}
			let result = res.data;
			
			// if 与后台规定的成功码是否正常
			if (result.code == 200 || result.code == 2003) {
				return result;
			}else if (result.code === 4004 || result.code === 4005) {
				// 如果正在刷新token，将请求加入队列并返回一个等待的Promise
				if (isRefreshingToken) {
					return queueRequest(res.config)
				}else{
					// 开始刷新token并重试请求
					return await refreshAndRetry(res.config);
				}
			}else if(result.code === 6001 || result.code === 6002  || result.code === 6003){
				// 清空队列
				tokenRefreshQueue = [];
				isRefreshingToken = false
				$store.dispatch('logOut'); // 清除token
				return false
			}else {
				if (res.config.custom.requestError) {
					vm.$u.toast(result.msg);
				}
			}
		} else {
			if (res.config.custom.requestError) {
				let errorMessage = codeMessage[res.statusCode] ? codeMessage[res.statusCode] : res.statusCode;
				vm.$u.toast(errorMessage);
			}
		}
		return false;
	}, (response) => {
		console.error('请求错误',response);
		if (response.config.custom.retry && response.config.custom.retry_number > 0) {
			response.config.custom.retry_number--;
			console.log(response.config.custom.retry_number);
			return uni.$u.http.request(response.config);
		}
		if (response.config.custom.requestError) {
			if(response.errMsg == 'request:fail abort statusCode:-1 timeout'){
				//超时的话主动重试一次
				// if(!response.config.custom.__retry){
				// 	response.config.custom.__retry = true;
				// 	return uni.$u.http.request(response.config); // Retry the request
				// }else{
				// 	vm.$u.toast(getApp().$t('request.error.timeout'));
				// }
				vm.$u.toast(getApp().$t('request.error.timeout'));
			}else if(response.errMsg){
				vm.$u.toast(getApp().$t("request.error.text"))
			}
		}
		if (response.config.custom.ShowLoading) {
			uni.hideLoading();
		}
		return Promise.reject(response)
	});
}

// 处理token刷新和重试请求
async function refreshAndRetry(config) {
	console.log(config);
	try {
		//如果刷新token不存在
		console.log(uni.getStorageSync('refresh_token'));
		if(!uni.getStorageSync('refresh_token')){
			throw new Error('Refresh token not found');
			return
		}
		let refreshRes = await handleTokenRefresh();
		//刷新成功了
		if(refreshRes){
			const refreshedResponse = await uni.$u.http.request(config);
			processAllQueuedRequests();
			return refreshedResponse;
		}else{
			return false;
		}
	} catch (error) {
		console.log(error);
		// 清空队列
		tokenRefreshQueue = [];
		isRefreshingToken = false
		$store.dispatch('logOut'); // 清除token
		throw error; // 抛出错误以便外部捕获
	}
}
// 处理队列中所有请求的函数
function processAllQueuedRequests() {
	while (tokenRefreshQueue.length > 0 && !isRefreshingToken) {
		const { resolve, config } = tokenRefreshQueue.shift();
		uni.$u.http.request(config).then(res=>{
			resolve(res);
		}).catch (error=>{
			resolve(Promise.reject(error));
		}) 
		// try {
		// 	const response = await uni.$u.http.request(config);
		// 	resolve(response);
		// } catch (error) {
		// 	resolve(Promise.reject(error));
		// }
	}
}
// 处理token刷新的函数
async function handleTokenRefresh(retryCount = 0) {
	console.log('刷新token来了');
	try {
		isRefreshingToken = true;
		//测试结束
		const refreshResponse = await uni.$u.http.post('/api/v6/Comm/refresh', $store.state.user.deviceInfo,{
			custom:{
				norefreshIntercept: true,
				noToken: true
			},
			header:{
				'authorization': `Bearer ${uni.getStorageSync('refresh_token')}`
			}
		});
		if(refreshResponse){
			if(refreshResponse.code == 200){
				uni.setStorageSync('token', refreshResponse.data.access_token)
				uni.setStorageSync('refresh_token', refreshResponse.data.refresh_token)
				return refreshResponse;
			}else{
				return false
			}
		}else{
			retryCount++;
			if (retryCount < 3) {
				return await handleTokenRefresh(retryCount);
			} else {
				throw new Error('Token refresh failed after 3 attempts.');
			} 
		}
	} catch (error) {
		throw error;
	}finally{
		isRefreshingToken = false;
	}
}
// 将请求加入队列的辅助函数
async function queueRequest(config) {
	return new Promise(resolve => {
		tokenRefreshQueue.push({ resolve, config });
	});
}
export default {
	install
}
